﻿using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Threading;

namespace MediaBrowserSL.RIA.Tools
{
    /// <summary>
    /// Upload/Dowload Tools
    /// </summary>
    public class FileServer
    {
        public delegate void OnFileUploaded(object sender, Exception error);
        public delegate void OnFileUploading(object sender, int progress, String progressFormat);

        BackgroundWorker bgw;
        private Stream fs;
        private String fileName;

        public event OnFileUploaded FileUploaded;
        public event OnFileUploading FileUploading;

        public void UploadFileAsync(string fileName, Stream data)
        {
            bgw = new BackgroundWorker();
            bgw.WorkerSupportsCancellation = true;
            bgw.WorkerReportsProgress = true;
            bgw.DoWork += bgw_DoWork;
            bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;

            bgw.ProgressChanged += (s, e) =>
           {
               long bytesReadTotal = (long)e.UserState;
               string progressFormat = String.Format("Sent {0} out of {1}"
                   , fileSizeString(bytesReadTotal), fileSizeString(fs.Length));
               if (FileUploading != null) { FileUploading(s, e.ProgressPercentage, progressFormat); }
           };

            fs = data;
            this.fileName = fileName.Trim();

            bgw.RunWorkerAsync();
        }

        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            byte[] b = new byte[57344];
            int bytesRead = fs.Read(b, 0, b.Length);
            long bytesReadTotal = bytesRead;
            while (bytesRead > 0)
            {
                if (bgw.CancellationPending)
                {
                    e.Cancel = true;
                    break;  // request is stopping
                }

                AutoResetEvent a = new AutoResetEvent(false);

                WebClient wc = new WebClient();
                wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
                string errormessage = string.Empty;
                wc.UploadStringCompleted += (s, e1) =>
                {
                    if (e1.Error != null)
                    {
                        errormessage = e1.Error.Message.ToString();
                        e.Cancel = true;
                    }
                    a.Set();
                };

                wc.UploadStringAsync(new Uri(AppSettings.getAppSetting("FileReceiverUrl")), "POST"
                   , "filename=+" + fileName + "&filestream="
                   + Convert.ToBase64String(b, 0, bytesRead));

                a.WaitOne();

                if (!String.IsNullOrEmpty(errormessage))
                {
                    throw new Exception("errormessage");
                }

                int percentComplete = (int)((float)bytesReadTotal / (float)fs.Length * 100);
                bgw.ReportProgress(percentComplete, (Object)bytesReadTotal);
                if (bgw.CancellationPending)
                {
                    e.Cancel = true;
                    break;  // request is stopping
                }

                bytesRead = fs.Read(b, 0, b.Length);
                bytesReadTotal += bytesRead;
            }
        }

        void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (FileUploaded != null) { FileUploaded(sender, e.Error); }
        }

        string fileSizeString(long bytes)
        {
            string f;
            if (bytes > 1073741824)
                f = String.Format("{0:0.00} Gb", (float)bytes / (float)1073741824);
            else if (bytes > 1048576)
                f = String.Format("{0:0.00} Mb", (float)bytes / (float)1048576);
            else if (bytes > 1024)
                f = String.Format("{0:0.00} Kb", (float)bytes / (float)1024);
            else
                f = String.Format("{0:0.00} bytes", bytes);
            return f;
        }
    }
}
